package com.tangding.hprose.api.server;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.base.Strings;
import com.tangding.cache.TableWatchingCache;
import com.tangding.cache.TableWatchingCache.TableWatchingVO;
import com.tangding.common.exception.GException;
import com.tangding.common.logx.LogHelp;
import com.tangding.common.utils.JacksonUtil;
import com.tangding.hprose.api.client.HproseAsClient;
import com.tangding.hprose.api.server.command.impl.watch.WatchingTable;
import com.tangding.net.handler.MessageRes;
import com.tangding.net.pool.BaseNettySessionPool;

/**
 * @description 
 *
 * @author Ranger
 * @version 2017年12月26日_下午3:12:34
 *
 */
@Component
public class HproseApiServer4GameServer {
	
	static BaseNettySessionPool pool;
	@Autowired
	public void setPool(BaseNettySessionPool pool) {
		HproseApiServer4GameServer.pool = pool;
	}

	protected static ExecutorService poolExe = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() * 2);
	
	/**
	 * 保持心跳
	 * 
	 * @return
	 */
	public static boolean Heartbeat() {
		return true;
	}
	
	public static void TableTrigger(String gameName, String tableId) {
		if (!TableWatchingCache.hasBeenWatching(tableId)) {//桌子没有管理员监控
			return;
		}
		Map<String, Object> request = new HashMap<>();
		request.put("gameName", gameName);
		request.put("tableId", tableId);
		request.put("showCondition", 7);
		poolExe.submit(new Runnable() {
			@SuppressWarnings("unchecked")
			public void run() {
				try {
					Object result = HproseAsClient.invoke("QueryTableDetails", request);
					Map<String, Object> receivedData = new HashMap<>();
					if (result != null) {
						receivedData = JacksonUtil.readValue(JacksonUtil.toJson(result), Map.class);
					}
					receivedData.put("gameName", gameName);
					receivedData.put("tableId", tableId);
					//role 1 用户 2 管理员 3 机器人
					List<String> keys = TableWatchingCache.getKeysList();
					for (String uid : keys) {
						TableWatchingVO vo = TableWatchingCache.getWatchingVO(uid, tableId);
						if (vo != null) {
							Map<String, Object> finalData = WatchingTable.buildFinalData(vo.getCondition(), receivedData);
							pool.doResponse(uid, "UpdateTableDetails", finalData);
						}
					}
				} catch (GException e) {
					LogHelp.doLogAppErr(e);
				}
			}
		});
	}
	
	public static void UpdateTableDetails(String gameName, String tableId, Map<String, Object> receivedData) {
		poolExe.submit(new Runnable() {
			public void run() {
				receivedData.put("gameName", gameName);
				receivedData.put("tableId", tableId);
				//role 1 用户 2 管理员 3 机器人
				List<String> keys = TableWatchingCache.getKeysList();
				for (String uid : keys) {
					TableWatchingVO vo = TableWatchingCache.getWatchingVO(uid, tableId);
					if (vo != null) {
						Map<String, Object> finalData = WatchingTable.buildFinalData(vo.getCondition(), receivedData);
						pool.doResponse(uid, "UpdateTableDetails", finalData);
					}
				}
			}
		});
	}
	
	public static void UpdateGMSlotOtherInfo(String tableId, Map<String, Object> map) {
		poolExe.submit(new Runnable() {
			public void run() {
				try {
					Map<String, Object> data = new HashMap<>();
					data.put("tableId", tableId);
					
					List<String> keys = TableWatchingCache.getKeysList();
					for (String uid : keys) {
						TableWatchingVO vo = TableWatchingCache.getWatchingVO(uid, tableId);
						if (vo != null) {
							pool.doResponse(uid, "UpdateGMSlotOtherInfo", map);
						}
					}
				} catch (Exception e) {
					LogHelp.doLogException(e);
				}
			}
		});
	}
	
	public static void GameServerInfo(Object request){
		@SuppressWarnings("unchecked")
		Map<String, Object> data = (Map<String, Object>) request;
		String tableId = (String) data.get("tableId");
		String gameName = (String) data.get("gameName");
		Long userId = (Long) data.get("userId");
		String msg = (String) data.get("msg");
		if (Strings.isNullOrEmpty(tableId) && Strings.isNullOrEmpty(gameName) && userId == null) {//广播消息
			if (Strings.isNullOrEmpty(msg)) {//消息为空
				return;
			}
			Collection<String> onlines = pool.onlines();
			if (onlines != null && onlines.size() > 0) {//给所有在线管理员发送
				poolExe.submit(new Runnable() {
					public void run() {
						for (String uid : onlines) {
							pool.doResponse(uid, "GameServerInfo", msg);
						}
					}
				});
			}
		}else if (!Strings.isNullOrEmpty(tableId) && Strings.isNullOrEmpty(gameName) && userId == null) {//只针对桌子
			poolExe.submit(new Runnable() {
				public void run() {
					List<String> keys = TableWatchingCache.getKeysList();
					for (String uid : keys) {
						TableWatchingVO vo = TableWatchingCache.getWatchingVO(uid, tableId);
						if (vo != null) {
							pool.doResponse(uid, "GameServerInfo", msg);
						}
					}
				}
			});
		}
	}

	@SuppressWarnings("unchecked")
	public static void GameDataPush(MessageRes msg) {
		try {
			LogHelp.doLogTesting(JacksonUtil.toJson(msg));
			if ("TableTrigger".equals(msg.getCmd())) {
				Map<String, Object> data = (Map<String, Object>) msg.getData();
				Object gameName = data.get("gameName");
				Object tableId = data.get("tableId");
				if (tableId != null) {
					TableTrigger((String) gameName, (String) tableId);
				}
			}else if ("UpdateGMSlotOtherInfo".equals(msg.getCmd())) {
				Map<String, Object> data = (Map<String, Object>) msg.getData();
				Object tableId = data.get("tableId");
				if (tableId != null) {
					UpdateGMSlotOtherInfo((String) tableId, data);
				}
			}else if ("UpdateTableDetails".equals(msg.getCmd())) {
				Map<String, Object> data = (Map<String, Object>) msg.getData();
				Object tableId = data.get("tableId");
				Object gameName = data.get("gameName");
				if (tableId != null) {
					UpdateTableDetails((String) tableId, (String) gameName, data);
				}
			}else if ("GameServerInfo".equals(msg.getCmd())) {
				GameServerInfo(msg.getData());
			}
		} catch (Exception e) {
			LogHelp.doLogAppErr("game server push data illegal:[" + JacksonUtil.toJson(msg) + "]");
		}
	}
}